package login

import (
	"fmt"
	"log"
	"my-gameserver-go/core/mynet/conn"
	"my-gameserver-go/core/mynet/handler/abs"
	"my-gameserver-go/logic/consts"
	enums_ctxstate "my-gameserver-go/logic/consts/enums"
	"my-gameserver-go/logic/db"
	"my-gameserver-go/logic/message"
	persis "my-gameserver-go/logic/persistenceObj"
	player_mananger "my-gameserver-go/logic/player/manager"
	"my-gameserver-go/logic/structs"
	"my-gameserver-go/proto/c2s"
	"my-gameserver-go/proto/s2c"
	"time"
)

type Manager struct {
}

var InsLoginManager *Manager

//初始化方式
func init() {
	InsLoginManager = &Manager{}
}
func (loginManager *Manager) Login(gameConn *conn.GameConnection, msg *c2s.C2SLoginMessage) {
	if gameConn.Attr(consts.ChannelInfo) != nil {
		log.Println("channelInfo not nil  repeat login req!")
		return
	}
	connState := gameConn.Attr(consts.ConnPlayerState)
	if connState == nil {
		log.Println("connState is nil userName:!", msg.GetUserName())
		return
	}
	if connState != enums_ctxstate.CONNECT {
		loginManager.LoginFail(gameConn, consts.CONN_STATE_CODE_ERR, fmt.Sprint("loginstate is:", connState))
		return
	}
	gameConn.SetAttr(consts.ConnPlayerState, enums_ctxstate.VERIFY_ACCOUNT)
	//用户查找
	ok, err := db.UserAccess.HasUser(msg.UserName)
	var user *persis.User
	if err == nil {
		if !ok {
			user = persis.NewUser(msg.UserName)
			log.Println("create user and save! ")
		} else {
			user = db.UserAccess.FindUserByUserName(msg.UserName)
		}
		if user == nil {
			return
		}
		db.UserAccess.Save(user)
	} else {
		log.Println("find user has err:", err)
		return
	}
	//设置ChannelInfo
	gameConn.SetAttr(consts.ChannelInfo, structs.ChannelInfo{
		UserId:   user.UserId,
		UserName: user.UserName,
	})
	//内存中查找player
	player, ok := player_mananger.InsPlayerManager.GetPlayerByConn(gameConn.Conn)
	//数据库加载
	if ok {
		//是否顶号
		oldConn := player.Conn
		//开始顶号
		if oldConn != nil {
			//清除channel信息
			gameConn.ClearAttr(consts.ChannelInfo)
			//标记为顶号状态
			oldConn.SetAttr(consts.ConnPlayerState, enums_ctxstate.BE_REPLACE_ACCOUNT)
			//告知之前的连接被顶号并且关闭连接
			loginManager.sendAndClose(gameConn)
		}
	} else {
		gameConn.SetAttr(consts.ConnPlayerState, enums_ctxstate.VERIFY_DB)
		//数据库加载
		ok, err = db.PlayerAccess.HasPlayerByUserId(user.UserId)
		if err == nil {
			//TODO 创建player 抛事件
			if !ok {
				player = persis.NewPlayer(msg)
			} else {
				player = db.PlayerAccess.FindPlayerByUserId(user.UserId)
			}
			if player == nil {
				return
			}
			db.PlayerAccess.Save(player)
		} else {
			log.Println("find player has err:", err)
			return
		}

	}
	//转到玩家routine去初始化玩家
	player_mananger.InsPlayerManager.InnerHandlerSend(player.RoutineChanIndex, abs.NewInnerHandler(func() {
		player_mananger.InsPlayerManager.PlayerInit(player, gameConn)
	}))
}

func (loginManager *Manager) sendAndClose(conn *conn.GameConnection) {
	log.Println(fmt.Sprintf(consts.LOG_LOGIN_PREFIX + "off_site_landiong: %d" + "ctx:" + conn.LogInfo()))
	if conn.Isclosed {
		return
	}
	msg := &s2c.S2CLoginMessage{ServerTime: int32(time.Now().Second())}
	resMsg, ok := structs.NewResMessageStruct(int32(s2c.S2CLoginMessage_eMsgID), consts.OFF_SITE_LANDING, msg)
	if !ok {
		return
	}
	message.InsMessageManager.ConnSendAndClose(conn, resMsg)
}

//LoginFail 登陆失败
func (loginManager *Manager) LoginFail(conn *conn.GameConnection, errCode int32, errorInfo string) {
	log.Println(fmt.Sprintf(consts.LOG_LOGIN_PREFIX+"loginFaild.errorCode: %d"+"ctx:"+conn.LogInfo()+errorInfo, errCode))
	if conn.Isclosed {
		return
	}
	msg := &s2c.S2CLoginMessage{ServerTime: int32(time.Now().Second())}
	resMsg, ok := structs.NewResMessageStruct(int32(s2c.S2CLoginMessage_eMsgID), consts.CONN_STATE_CODE_ERR, msg)
	if !ok {
		return
	}
	message.InsMessageManager.ConnSend(conn, resMsg)
}
